package cn.com.Kol.ITPMP.System;

import com.xiaoleilu.hutool.date.DateUtil;
import org.beetl.sql.core.*;
import org.beetl.sql.core.db.ColDesc;
import org.beetl.sql.core.db.MySqlStyle;
import org.beetl.sql.core.db.TableDesc;
import org.beetl.sql.ext.DebugInterceptor;
import org.springblade.core.beetl.BeetlMaker;
import org.springblade.core.support.CMap;
import org.springblade.gen.CodeGenerator;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author Kol
 * @date 2019/03/06
 */
public class Gen {

    public static String MODULES = "";
    public static String MODULES_PACKAGE = "";
    public static String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
    public static String JDBC_USER_NAME = "root";
    public static String JDBC_PASSWORD = "8182";
    public static String JDBC_URL = "jdbc:mysql://localhost/itpmp?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true";
    private static String PROJECT_PATH = System.getProperty("user.dir");
    private static String TEMPLATE_FILE_PATH;
    private static String JAVA_PATH;
    private static String RESOURCES_PATH;
    public static String CONTROLLER_PACKAGE;
    public static String MODEL_PACKAGE;
    public static String SERVICE_PACKAGE;
    public static String SERVICE_IMPL_PACKAGE;
    private static String PACKAGE_PATH_CONTROLLER;
    private static String PACKAGE_PATH_MODEL;
    private static String PACKAGE_PATH_SERVICE;
    private static String PACKAGE_PATH_SERVICE_IMPL;
    private static String AUTHOR;
    private static String DATE;

    public Gen() {
    }

    public static void gen(String moduleName, String packageName, String templatePath, List<CMap> modules) throws Exception {
        MODULES = moduleName;
        MODULES_PACKAGE = packageName;
        CONTROLLER_PACKAGE = MODULES_PACKAGE + "." + MODULES + ".controller";
        MODEL_PACKAGE = MODULES_PACKAGE + "." + MODULES + ".model";
        SERVICE_PACKAGE = MODULES_PACKAGE + "." + MODULES + ".service";
        String SERVICE_IMPL_PACKAGE = SERVICE_PACKAGE + ".impl";
        PACKAGE_PATH_CONTROLLER = packageConvertPath(CONTROLLER_PACKAGE);
        PACKAGE_PATH_MODEL = packageConvertPath(MODEL_PACKAGE);
        PACKAGE_PATH_SERVICE = packageConvertPath(SERVICE_PACKAGE);
        PACKAGE_PATH_SERVICE_IMPL = packageConvertPath(SERVICE_IMPL_PACKAGE);
        genCode(modules);
    }

    public static void main(String[] args) throws Exception {
        List<CMap> list = new ArrayList<CMap>();
        list.add(CMap.init().set("modelName", "Area").set("tableName", "Area"));
        try {
            gen("initiative", "com.Kol", System.getProperty("user.dir"), list);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void genCode(List<CMap> list) throws Exception {
        Iterator var1 = list.iterator();

        while(var1.hasNext()) {
            CMap map = (CMap)var1.next();
            String modelName = map.getStr("modelName");
            String tableName = map.getStr("tableName");
            String pkName = map.getStr("pkName");
            genModel(modelName, tableName, pkName);
            genController(modelName, tableName, pkName);
            genService(modelName, tableName, pkName);
            genSql(modelName, tableName, pkName);
        }

    }

    public static void genController(String modelName, String tableName, String pkName) {
        try {
            Map<String, Object> data = getData(modelName, tableName, pkName);
            String path = PROJECT_PATH + JAVA_PATH + PACKAGE_PATH_CONTROLLER + modelName + "Controller.java";
            File file = new File(path);
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }

            BeetlMaker.makeFile(CodeGenerator.class.getClassLoader().getResource("generator/template/controller.btl"), data, path);
            System.out.println("[ " + DateUtil.now() + " ]   " + modelName + "Controller.java 生成成功");
        } catch (Exception var6) {
            throw new RuntimeException("[ " + DateUtil.now() + " ]   生成Controller失败", var6);
        }
    }

    public static void genService(String modelName, String tableName, String pkName) {
        try {
            Map<String, Object> data = getData(modelName, tableName, pkName);
            String path = PROJECT_PATH + JAVA_PATH + PACKAGE_PATH_SERVICE + modelName + "Service.java";
            File file = new File(path);
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }

            BeetlMaker.makeFile(CodeGenerator.class.getClassLoader().getResource("generator/template/service.btl"), data, path);
            System.out.println("[ " + DateUtil.now() + " ]   " + modelName + "Service.java 生成成功");
            String path1 = PROJECT_PATH + JAVA_PATH + PACKAGE_PATH_SERVICE_IMPL + modelName + "ServiceImpl.java";
            File file1 = new File(path1);
            if (!file1.getParentFile().exists()) {
                file1.getParentFile().mkdirs();
            }

            BeetlMaker.makeFile(CodeGenerator.class.getClassLoader().getResource("generator/template/serviceimpl.btl"), data, path1);
            System.out.println("[ " + DateUtil.now() + " ]   " + modelName + "ServiceImpl.java 生成成功");
        } catch (Exception var8) {
            throw new RuntimeException("[ " + DateUtil.now() + " ]   生成Service失败", var8);
        }
    }

    public static void genModel(String modelName, String tableName, String pkName) throws Exception {
        try {
            Map<String, Object> data = getData(modelName, tableName, pkName);
            setAttr(tableName, data);
            String path = PROJECT_PATH + JAVA_PATH + PACKAGE_PATH_MODEL + modelName + ".java";
            File file = new File(path);
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }

            BeetlMaker.makeFile(CodeGenerator.class.getClassLoader().getResource("generator/template/model.btl"), data, path);
            System.out.println("[ " + DateUtil.now() + " ]   " + modelName + ".java 生成成功");
        } catch (Exception var6) {
            throw new RuntimeException("[ " + DateUtil.now() + " ]   生成Service失败", var6);
        }
    }

    public static void genSql(String modelName, String tableName, String pkName) throws Exception {
        try {
            Map<String, Object> data = getData(modelName, tableName, pkName);
            String path = PROJECT_PATH + RESOURCES_PATH + "/sql/" + modelName.toLowerCase() + ".md";
            File file = new File(path);
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }

            BeetlMaker.makeFile(CodeGenerator.class.getClassLoader().getResource("generator/template/sql.btl"), data, path);
            System.out.println("[ " + DateUtil.now() + " ]   " + modelName.toLowerCase() + ".md 生成成功");
        } catch (Exception var6) {
            throw new RuntimeException("[ " + DateUtil.now() + " ]   生成Service失败", var6);
        }
    }

    private static Map<String, Object> getData(String modelName, String tableName, String pkName) {
        Map<String, Object> data = new HashMap();
        data.put("date", DATE);
        data.put("author", AUTHOR);
        data.put("packageName", MODULES_PACKAGE + "." + MODULES);
        data.put("modelName", modelName);
        data.put("lowerModelName", modelName.toLowerCase());
        data.put("tableName", tableName);
        data.put("pkName", pkName);
        data.put("model", MODULES);
        return data;
    }

    private static String packageConvertPath(String packageName) {
        return String.format("/%s/", packageName.contains(".") ? packageName.replaceAll("\\.", "/") : packageName);
    }

    private static SQLManager getSqlManager() {
        MySqlStyle style = new MySqlStyle();
        ConnectionSource source = ConnectionSourceHelper.getSimple(JDBC_DRIVER, JDBC_URL, JDBC_USER_NAME, JDBC_PASSWORD);
        SQLLoader loader = new ClasspathLoader("/sql");
        SQLManager sql = new SQLManager(style, loader, source, new UnderlinedNameConversion(), new Interceptor[]{new DebugInterceptor()});
        return sql;
    }

    private static void setAttr(String tableName, Map<String, Object> data) {
        SQLManager sm = getSqlManager();
        TableDesc tableDesc = sm.getMetaDataManager().getTable(tableName);
        data.put("remark", tableDesc.getRemark());
        final Set<String> idNames = tableDesc.getIdNames();
        Set<String> cols = tableDesc.getCols();
        List<Map<String, Object>> attrs = new ArrayList();
        boolean tempDouble = false;
        boolean tempDate = false;
        Iterator var9 = cols.iterator();

        String CR;
        while(var9.hasNext()) {
            CR = (String)var9.next();
            ColDesc desc = tableDesc.getColDesc(CR);
            Map<String, Object> attr = new HashMap();
            attr.put("comment", desc.remark);
            String attrName = sm.getNc().getPropertyName((Class)null, desc.colName);
            attr.put("name", attrName);
            attr.put("methodName", getMethodName(attrName));
            attr.put("type", desc.remark);
            String type = JavaType.getType(desc.sqlType, desc.size, desc.digit);
            if (type.equals("Double")) {
                type = "BigDecimal";
                tempDouble = true;
            }

            if (type.equals("Timestamp")) {
                type = "Date";
                tempDate = true;
            }

            attr.put("type", type);
            attr.put("desc", desc);
            attrs.add(attr);
        }

        Collections.sort(attrs, new Comparator<Map<String, Object>>() {
            public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                ColDesc desc1 = (ColDesc)o1.get("desc");
                ColDesc desc2 = (ColDesc)o2.get("desc");
                int score1 = this.score(desc1);
                int score2 = this.score(desc2);
                return score1 == score2 ? desc1.colName.compareTo(desc2.colName) : score2 - score1;
            }

            private int score(ColDesc desc) {
                if (idNames.contains(desc.colName)) {
                    return 99;
                } else if (JavaType.isInteger(desc.sqlType)) {
                    return 9;
                } else {
                    return JavaType.isDateType(desc.sqlType) ? -9 : 0;
                }
            }
        });
        String srcHead = "";
        CR = System.getProperty("line.separator");
        if (tempDate) {
            srcHead = srcHead + "import java.util.Date;" + CR;
        }

        if (tempDouble) {
            srcHead = srcHead + "import java.math.BigDecimal;" + CR;
        }

        data.put("attrs", attrs);
        data.put("imports", srcHead);
    }

    private static String getMethodName(String name) {
        char ch1 = name.charAt(0);
        char ch2 = name.charAt(1);
        if (Character.isLowerCase(ch1) && Character.isUpperCase(ch2)) {
            return name;
        } else if (Character.isUpperCase(ch1) && Character.isUpperCase(ch2)) {
            return name;
        } else {
            char upper = Character.toUpperCase(ch1);
            return upper + name.substring(1);
        }
    }

    static {
        TEMPLATE_FILE_PATH = PROJECT_PATH + "/src/main/resources/generator/template/";
        JAVA_PATH = "/src/main/java";
        RESOURCES_PATH = "/src/main/resources";
        CONTROLLER_PACKAGE = MODULES_PACKAGE + "." + MODULES + ".controller";
        MODEL_PACKAGE = MODULES_PACKAGE + "." + MODULES + ".model";
        SERVICE_PACKAGE = MODULES_PACKAGE + "." + MODULES + ".service";
        SERVICE_IMPL_PACKAGE = SERVICE_PACKAGE + ".impl";
        PACKAGE_PATH_CONTROLLER = packageConvertPath(CONTROLLER_PACKAGE);
        PACKAGE_PATH_MODEL = packageConvertPath(MODEL_PACKAGE);
        PACKAGE_PATH_SERVICE = packageConvertPath(SERVICE_PACKAGE);
        PACKAGE_PATH_SERVICE_IMPL = packageConvertPath(SERVICE_IMPL_PACKAGE);
        AUTHOR = "Kol";
        DATE = (new SimpleDateFormat("yyyy/MM/dd")).format(new Date());
    }
}
